#pragma once

#include <cstddef>
#include <cstdint>

void ReturnsVoid() {}

std::nullptr_t ReturnsNullptr()
{
    return nullptr;
}
std::nullptr_t PassAndReturnsNullptr(std::nullptr_t t)
{
    return t;
}

bool ReturnsBool()
{
    return true;
}
bool PassAndReturnsBool(bool v)
{
    return v;
}

// Character types
char ReturnsChar()
{
    return 'a';
}
signed char ReturnsSChar()
{
    return 'a';
}
unsigned char ReturnsUChar()
{
    return 'a';
}
char PassAndReturnsChar(char v)
{
    return v;
}
signed char PassAndReturnsSChar(signed char v)
{
    return v;
}
unsigned char PassAndReturnsUChar(unsigned char v)
{
    return v;
}


wchar_t ReturnsWChar()
{
    return 'a';
}
#if __cplusplus > 201703L
char8_t ReturnsChar8()
{
    return 'a';
}
#endif
char16_t ReturnsChar16()
{
    return 'a';
}
char32_t ReturnsChar32()
{
    return 'a';
}

// Floating-point types
float ReturnsFloat()
{
    return 5.0;
}
double ReturnsDouble()
{
    return -5.0;
}
long double ReturnsLongDouble()
{
    return -5.0;
}

float PassAndReturnsFloat(float v)
{
    return v;
}
double PassAndReturnsDouble(double v)
{
    return v;
}
long double PassAndReturnsLongDouble(long double v)
{
    return v;
}

// Integer types
int8_t ReturnsInt8()
{
    return -5;
}
uint8_t ReturnsUInt8()
{
    return 5;
}
int16_t ReturnsInt16()
{
    return -5;
}
uint16_t ReturnsUInt16()
{
    return 5;
}
int32_t ReturnsInt32()
{
    return -5;
}
uint32_t ReturnsUInt32()
{
    return 5;
}
#if !defined(__EMSCRIPTEN__)
int64_t ReturnsInt64()
{
    return -5;
}
uint64_t ReturnsUInt64()
{
    return 5;
}
#endif

int8_t PassAndReturnsInt8(int8_t v)
{
    return v;
}
uint8_t PassAndReturnsUInt8(uint8_t v)
{
    return v;
}
int16_t PassAndReturnsInt16(int16_t v)
{
    return v;
}
uint16_t PassAndReturnsUInt16(uint16_t v)
{
    return v;
}
int32_t PassAndReturnsInt32(int32_t v)
{
    return v;
}
uint32_t PassAndReturnsUInt32(uint32_t v)
{
    return v;
}
int64_t PassAndReturnsInt64(int64_t v)
{
    return v;
}
uint64_t PassAndReturnsUInt64(uint64_t v)
{
    return v;
}

// Pointer types
const char* ReturnsConstCharPtr()
{
    return "Hello";
}
const char* PassAndReturnsConstCharPtr(const char* ptr)
{
    return ptr;
}
